import os
import psutil
import tkinter as tk
from tkinter import ttk, messagebox, filedialog

class ProcessTerminatorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("进程终止工具")
        self.root.geometry("800x500")
        
        # 创建主框架
        self.main_frame = ttk.Frame(root, padding="10")
        self.main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 目录选择部分
        self.dir_frame = ttk.LabelFrame(self.main_frame, text="目标目录", padding="10")
        self.dir_frame.pack(fill=tk.X, pady=5)
        
        # 路径输入框和按钮
        self.dir_entry = ttk.Entry(self.dir_frame, width=70)
        self.dir_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 5))
        
        # 新增：粘贴按钮
        self.paste_btn = ttk.Button(self.dir_frame, text="粘贴", command=self.paste_path, width=6)
        self.paste_btn.pack(side=tk.LEFT, padx=(0, 5))
        
        # 浏览按钮
        self.browse_btn = ttk.Button(self.dir_frame, text="浏览...", command=self.browse_directory, width=8)
        self.browse_btn.pack(side=tk.LEFT)
        
        # 进程列表部分
        self.process_frame = ttk.LabelFrame(self.main_frame, text="进程列表", padding="10")
        self.process_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        self.tree = ttk.Treeview(self.process_frame, columns=('pid', 'name', 'path'), show='headings')
        self.tree.heading('pid', text='PID')
        self.tree.heading('name', text='进程名')
        self.tree.heading('path', text='路径')
        self.tree.column('pid', width=100, anchor='center')
        self.tree.column('name', width=150, anchor='center')
        self.tree.column('path', width=450)
        
        self.scrollbar = ttk.Scrollbar(self.process_frame, orient=tk.VERTICAL, command=self.tree.yview)
        self.tree.configure(yscrollcommand=self.scrollbar.set)
        
        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.tree.pack(fill=tk.BOTH, expand=True)
        
        # 按钮部分
        self.btn_frame = ttk.Frame(self.main_frame)
        self.btn_frame.pack(fill=tk.X, pady=5)
        
        self.refresh_btn = ttk.Button(self.btn_frame, text="刷新列表", command=self.refresh_process_list)
        self.refresh_btn.pack(side=tk.LEFT, padx=5)
        
        self.terminate_btn = ttk.Button(self.btn_frame, text="终止选中进程", command=self.terminate_selected)
        self.terminate_btn.pack(side=tk.LEFT, padx=5)
        
        self.terminate_all_btn = ttk.Button(self.btn_frame, text="终止所有匹配进程", command=self.terminate_all_in_directory)
        self.terminate_all_btn.pack(side=tk.RIGHT, padx=5)
        
        # 状态栏
        self.status_var = tk.StringVar()
        self.status_bar = ttk.Label(self.main_frame, textvariable=self.status_var, relief=tk.SUNKEN)
        self.status_bar.pack(fill=tk.X, pady=(5, 0))
        
        # 初始加载
        self.dir_entry.insert(0, r'D:/')
        self.refresh_process_list()
    
    def paste_path(self):
        """粘贴剪贴板中的路径"""
        try:
            clipboard_text = self.root.clipboard_get()
            if clipboard_text.strip():
                self.dir_entry.delete(0, tk.END)
                self.dir_entry.insert(0, clipboard_text)
                self.refresh_process_list()
        except tk.TclError:
            messagebox.showwarning("提示", "剪贴板中没有文本内容！")
    
    def browse_directory(self):
        """选择目录"""
        directory = filedialog.askdirectory()
        if directory:
            self.dir_entry.delete(0, tk.END)
            self.dir_entry.insert(0, directory)
            self.refresh_process_list()
    
    def refresh_process_list(self):
        """刷新进程列表"""
        directory = self.dir_entry.get().strip()
        if not directory:
            messagebox.showwarning("警告", "请先指定目录路径")
            return
            
        directory = os.path.normpath(directory)  # 标准化路径
        
        # 清空现有列表
        for item in self.tree.get_children():
            self.tree.delete(item)
            
        found_processes = 0
        
        # 获取并显示匹配的进程
        for proc in psutil.process_iter(['pid', 'name', 'exe']):
            try:
                if proc.info['exe']:
                    proc_path = os.path.normpath(proc.info['exe'])
                    if directory in proc_path:
                        self.tree.insert('', tk.END, values=(
                            proc.info['pid'],
                            proc.info['name'],
                            proc.info['exe']
                        ))
                        found_processes += 1
            except psutil.AccessDenied:
                self.status_var.set(f"无权限访问进程: {proc.info.get('name')} (PID: {proc.info.get('pid')})")
            except (psutil.NoSuchProcess, psutil.ZombieProcess):
                pass
        
        self.status_var.set(f"找到 {found_processes} 个匹配进程 | 目录: {directory}")
    
    def terminate_selected(self):
        """终止选中的进程"""
        selected_items = self.tree.selection()
        if not selected_items:
            messagebox.showwarning("警告", "请先选择要终止的进程")
            return
            
        terminated = 0
        failed = 0
        
        for item in selected_items:
            pid = int(self.tree.item(item, 'values')[0])
            try:
                process = psutil.Process(pid)
                process.terminate()
                process.wait(timeout=3)
                self.tree.delete(item)
                terminated += 1
            except Exception as e:
                failed += 1
                messagebox.showerror("错误", f"无法终止进程 {pid}: {str(e)}")
        
        self.status_var.set(f"已终止 {terminated} 个进程 | 失败 {failed} 个")
        self.refresh_process_list()
    
    def terminate_all_in_directory(self):
        """终止目标目录下的所有进程"""
        directory = self.dir_entry.get().strip()
        if not directory:
            messagebox.showwarning("警告", "请先指定目录路径")
            return
            
        directory = os.path.normpath(directory)
        terminated = 0
        failed = 0
        
        for proc in psutil.process_iter(['pid', 'name', 'exe']):
            try:
                if proc.info['exe']:
                    proc_path = os.path.normpath(proc.info['exe'])
                    if directory in proc_path:
                        proc.terminate()
                        proc.wait(timeout=3)
                        terminated += 1
            except Exception as e:
                failed += 1
        
        messagebox.showinfo("完成", f"已终止 {terminated} 个进程\n{failed} 个进程终止失败")
        self.refresh_process_list()

if __name__ == "__main__":
    root = tk.Tk()
    app = ProcessTerminatorApp(root)
    root.mainloop()